20 April 2022:
================================================================================
Converted the ZX81 graphics as-is, minus the hatched bits (because PETSCII doesn't have the right hatched section). [IL01]


21 April 2022:
================================================================================
Discovered C64-List and found it could be jerry-rigged to produce VIC programs (via loading it into a C64 first and saving it on tape). https://www.c64-wiki.com/wiki/C64list
Investigated UDGs and pixel-plotting on the VIC (which are two sides of the same coin).
https://archive.org/details/your-computer-magazine-1981-10/page/n28/mode/1up?view=theater
Probably best to make the game work first and see how much memory it takes, though...
Ideally, want to avoid using the Super Expander cartridge.
Will need to add Block 1 (8K, total 11,775 bytes free at startup) at least.
Block 0 by itself gives 6K total but is ignored if blocks 1-3 are selected.
6K has no chance of being enough with all those control characters everywhere...
Moved pyramid up half a block and drew all the shading that can be done without UDGs and modified the Evil Eye to use the quarter-circle graphics [IL02] - the latter of these was undone because the eye was too square.
Added red to the eye, the ROT13 routine and the victory/defeat sequences to test it [IL03].
Added the "Another game" routine, a BASIC version of the Illuminati Code and a few lines to test it (and it works!) [IL04]
Added the score fuse, which needed to decrease by a half-square every time owing to the cramped screen conditions. [IL05]


22 April 2022:
================================================================================
Added the code input and error checking routine. This needed a huge amount of debugging, and was only partially successful... [IL06]
Already above 4K, so will need the 8K expansion. Printing in the far bottom right corner of the screen causes it to scroll - don't want that. Had to discover that the screen and colour memory move if there is more than a 3K expansion:
https://www.lemon64.com/forum/viewtopic.php?t=64532
Screen changes from 1E00h-1FFFh to 1000h-11FFh.
Colour changes from 9600h-97FFh to 9400h-95FFh.
Accidentally discovered that adding 128 to a POKE to the screen memory prints the inverse character, which I need.
Some much-needed renumbering done, and finished the debugging of this section. [IL07]
Added the "build the pyramid" and "did that hit?" sections - so this should be a complete game bar the title page and instructions. [IL08]


23 April 2022:
================================================================================
The Spectrum's 40th birthday.

You really think I'm going to write programs on a *Commodore* machine on *that* day?

Well, do you?


24 April 2022:
================================================================================
Drew the Chunk-o-Vision title logo. Some compromises have had to be made with the Lords of Midnight font (turned it into the narrow Minecraft version from the Hammer of Retribution resource pack) to get it to fit into the VIC's compromised screen. But it gets the point across. [IL09]
Discovered a PDF version of the enormous tome "Programming the VIC": https://vic20reloaded.com/5-vic-20-docs-you-should-have/ - reveals the secrets of UDGs on the VIC-20 (page 401 onwards). This should be useful... later.


25 April 2022:
================================================================================
Added the introductory screens and instructions. [IL10]
RUN il10 and PRINTFRE(0) after running, and we have 3,794 bytes remaining.

And now for the black art of VIC UDGs...

Character definition program (12-32)
For the 8K expansion: POKE 648,30: SYS 64818 where this needs to be changed.
Type this before loading - POKE 648,30 changes the start of the screen to ????? then SYS 64818 resets the VIC but retains the non-standard BASIC configuration.
PEEK(648)=16 on an 8K expanded model = 16, but 30 on an unexpanded model.
So this POKE is just to make an unexpanded listing work on an expanded model.
The game itself is complete at this stage. Just need to find a way to:
- move RAMTOP down by 3K (or maybe 2.5K will do)
- LDIR the character set into the top 2K of what we've just reserved, probably has to be in MC for speed more than anything else
- POKE the new characters into this character set, which doesn't necessarily have to be done in MC, but if we could, so much the better
- write the MC for the Illuminati's Top Secret Code.

From the manual: POKE 36869,240 changes the character set back to normal.
Can't just POKE at the addresses where the characters are stored. That would have made it a lot easier.

Slogging through "Programming the VIC"'s program 12-32 to define UDGs on an UNEXPANDED VIC I finally thought I'd look up if there was a specific way to do it on an expanded model...
http://www.boray.se/commodore/boray_expanded_vic-20.pdf
So it seems I have to manually move the BASIC block entirely into the expansion RAM.
Can it be done (with the program as it is)?

11,773 bytes free at startup. Run it through a victory game (and don't CLR the variables) and 3,741 bytes are left. 8,032 bytes used so REALISTICALLY, will need to move to a 16K expansion to keep it all going. (BLK1+BLK2 runs from 2000h-5FFFh, i.e. 8192-24575.)
16K expansion: 19,965 bytes free with PRINTFRE(0).
The magic incantation from Sweden:
POKE44,32:POKE8192,0:NEW
Now 16,381 bytes free. Load IL10 as before, RUN a victory game, now 8,349 bytes free. 8,032 bytes used as before.

Things to be learned from the Swedish article:
- it's possible to put graphics in the tape buffer, which could be exactly what I'm looking for.
	= POKE36869,(PEEK(36869)AND240)+8
	= Chars 83-95 appear at 664 and chars 103-127 appear at 824.
	= THAT DIDN'T WORK, because the entire character set needs to be shifted to that area...
	= Anders' SNOW20BAS.PRG shows that it's EITHER a redefined entire character set if we want to have regular characters on screen at the same time, OR just a few UDGs and nothing else!
- AND is a bitwise operator so it should be possible to simplify the BASIC version of the Illuminati code, for now!

HENCE: if the only realistic way to have UDGs *and* regular characters on screen is to dump the entire character set into BLK0 and redefine bits of it so that a POKE and a reset is required before loading, it's not worth it - hence the 3D effect on the pyramid has to be shelved (as it was always going to be on the PET version anyway; maybe it'll be OK on the C64, where there's none of this moving-screen-memory-around business). Also, change the BASIC Illuminati Code to the bitwise AND version (as it is on the QL in ILV12_BAS) and see if that works.

This revised version: 4,038 bytes free after running a winning game. 7,735 bytes used so it's slightly smaller (and the MC version will be smaller still). [IL11]

Just the machine code to go now...
Chapter 9 of "Programming the VIC" says that it's OK to put the machine code in a REM statement (line 0) before the rest of the program, as long as none of the bytes are 0. (There might be an equivalent short form of LD A,0 but if not, the recommendation is to use - in Z80-ese at least - LD A,1 followed by DEC A.)
PEEK(43)+256*PEEK(44) reveals the start of BASIC which should be 4609.
First byte in the REM statement is at 4614. Hence use 4614-4619 for the initial variables and SYS 4620 to execute, if I've got it right.

REM statement will only allow 80 bytes... have to do it above RAMTOP, then.
POKE56,63 to move RAMTOP to 16128 (which should be the first byte free for MC).
Start poking MC at 16134 just in case! (SYS 16140 to execute). 256 bytes available.

Getting nowhere fast with what seemed like a simple routine to convert character codes (48-57,65-70) to the values represented by that hex digit.

Solved with a rather cryptic message on Lemon64 (which I had hoped not to call on at all, and reveal the result). I'd sort-of-worked it out by myself and the truth was lurking in the next chapter of "Programming the VIC" with a complete descripton of CLC. Apparently, some galaxy-brain at MOS Technologies decided that the Carry flag set meant "DO carry if adding but DON'T carry if subtracting" and vice versa. Hence, SET the carry flag with SEC before SBC, and clear it with CLC before ADC.


26 April 2022:
================================================================================
The rest of the machine code pretty much fell into place after that...
Just have to transfer it into the main Illuminati program now!
First of all, do it via BASIC in the listing... [IL12]

...this version has a problem. "CPU Jam at $3F98" which is right near the top of available memory, after successfully performing six calculations.
Took the printer off - gets to seven but hits "CPU Jam" at $3F90.
WORKS with 16K, though - it must be a stack overflow or something like that!
Looks like we need to shove the MC a bit lower in memory. 3,516 bytes free after a successful game (bear in mind RAMTOP is within BLK1 so BLK2 is above this as well and is mostly blank!)

Brought down the MC by another 256 bytes. (Needed reassembly.) This is now working. [IL13]

Still, it's better to load in the code from outside rather than have all those DATA statements, so tried this, saving the code as a .SEQ file. [IL14] https://techtinkering.com/articles/saving-and-loading-memory-on-the-vic-20/
Using LOAD"IL14",8,1 doesn't auto-run it. And on reloading the code, the drive light flashes, so something's gone wrong. The program stops when the machine code is executed, although it doesn't crash completely.
PEEKing 15884-16007 reveals a load of 220s, which are the hatched-left graphics character. Either way, this isn't the code we want!
A minor change (looks like I should have used "ILCODE,S" for the filename) now beings "ILLEGAL QUANTITY ERROR IN 160"... [IL15]
It's actually worked properly until the 0 at byte 15971 - which has thrown the PRINT routine to save and load it, with the same problem that throws REM statements - use of CHR$(0) to make an unprintable character which can't be read back with the ASC function.
Try again, this time without the S parameter... [IL16]
It's still not gone well, because the PRINT is still there.
Page 49 of the 1570 manual suggests IF B$=""THENB$=CHR$(0) to get round this problem. IT WORKS! (I'm using the sequential file "ILCODE.SEQ".) [IL17]

Made the standalone disc. LOAD"ILLUMINATI",8 then RUN.

WE'RE STILL NOT OUT OF THE WOODS YET!

Tried the final version and after one failure, the CPU jam occurs on the second round. And to think there might need to be *16* rounds in total...
(It still works in 16K, though.)

Maybe I'll try the PET conversion while I'm waiting for advice...

ALSO MEANWHILE: If POKE 36879,27 is still in the final listing, this is apparently something I needed to do for UDGs and it can be taken out.
It should also be possible to trim down the code to draw the pyramid, with a loop to make all 15 cells rather than printing them all out long-hand. This might save bytes on the PET which would be useful.


27 April 2022:
================================================================================
Maybe the mystery with the jamming CPU has been solved...
https://www.lemon64.com/forum/viewtopic.php?p=966025#966025
Let's see. Make these changes...
[IL13A] is a copy of IL13 (which has the MC in the BASIC listing) with the extra POKE52,62:CLR at the top of the listing. Will it work, or crash?
[IL12A] is a copy of IL12 with the same alteration, except it's POKE52,63 because the code was loaded higher originally.
HENCE: code has been put back to where it was (as in IL12), the extra POKE applied, and the new code saved as a SEQ to be loaded in from externally.
PRINTFRE(0) gives 3,972 bytes free after a successful game. [IL18]

Next project: implement the smaller routine to build the pyramid from calculated locations (as tried on the PET while waiting for advice about the jamming CPU).
Now 4,034 bytes free after a successful game. [IL19]

Some improvements made in the listing to save more memory including getting rid of some % variables (the % symbols in the listing take up more space than the variables would save).
The ROT13 routine was a good one. Using SP and SC for all the POKEs to fill that bottom right square also helps. Now 4,225 bytes free after a successful game. [IL20]

The temptation of UDGs is still there...
First, will need to write a bit of MC to "LDIR" all 2K of the character set into the "correct" address.
Need to know where to go, though. PAGE 109 OF "PROGRAMMING THE VIC" IS THE DIAGRAM TO LOOK AT.
Screen is at 4096-4601 on expanded VIC, colour RAM is 37888-38393.
Screen is at 7680-8185 on unexpanded VIC, colour RAM is 38400-38905.
Character set is at 32768.
BASIC starts just above the screen on the expanded VIC. (This is bad!)

BUT we can (can't we?) save to disc and force the program to load in a particular block if it was saved with SAVE"...",8,1. Right?
So, according to Appendix G (p.578), to dump 2K of characters into a block of RAM below BASIC:
- it must occupy space 5120-7167, and is activated with POKE 36869,205
- BASIC starts at 7168. Hence there are 9216 bytes available.
	= (il20 is 7550 bytes. It may still grow a bit...)
- BASIC usually starts at 4608 - 11776 bytes available.

Will need to investigate loops that require more than 255 iterations...
...and this does not look encouraging!
https://github.com/skilldrick/6502js/issues/6
According to several forum posts (search for "ldir"):
LDA NNNN,x; STA NNNN,x; INX; BNE is the general sequence. (Just keep increasing X until it's done, except that we need to transfer 2048 bytes. Maybe just do it in blocks, 256 at a time?)
Do it eight times, maybe use Y as the second counter.


28 April 2022:
================================================================================
Found this: http://www.6502.org/source/general/memory_move.html
Won't need the routine to move the extra bytes (MD2-MD4) - this is fine for 256-byte blocks.
The routine can be trimmed down a bit - doesn't need the BEQ MD2 line or the bits that will transfer bytes that make up the remainder after a multiple of 256 has been done.
ALSO... it forced me to learn about the zero page, that VIC BASIC doesn't touch addresses 246-254 (F6h-FEh) and I can trim the Illuminati's code down to use zero page addressing. That'll save a few bytes and make it even faster.
(I wonder if the PET and C64 also leave this little bit of the zero page empty?)
[IL12B] is another test - is the new zero-page code OK?
Variables to be POKEd and PEEKed are now 248-253, SYS is 16132.

Move BASIC up to 8192, load il20, play a successful game and PRINTFRE(0) returns 641. Space is getting tight...!
It should be possible to poke the necessary UDGs from inside machine code.

Moving BASIC worked, the LDIR routine was fine. It looked like there was no need for it in the final program, because I intended to load the character set into the 2K from 5180 as a .SEQ file just like the code. However, either the writing or reading process (using PRINT#8 and GET#8) is introducing errors where checking the code sometimes returns a value 4 more than it should be.
Returning now to the LDIR version, using the full LDIR routine, calling it twice with different values, one set to transfer the whole character set and one to drop the UDGs into place.
Space is now getting tight in the MC area... and dropping the top of BASIC down another 256 bytes means there are only 385 bytes free after: IL20 loaded to 8192, and a successful game. (The line with POKE 55... was altered from 63 to 62.)

Finally brought all the code together, checked that it writes OK (it helps to put it on "virgin" space on the disc so that there are no errors), and now the latest version of the game will load all this code (230 bytes), which LDIRs the normal character set in place and the UDGs where they're needed. [IL21]
Loaded to BASIC at 8192, after a successful game... 555 bytes left! 


29 April 2022:
================================================================================
IL21 was a raging success - the game is nearly complete!
Some cosmetic changes. POKE 36879,27 was restored - this sets the border and paper colour correctly! Added the "LOADING CODE..." prompt (more useful on the tape version), tidied up the drawing of the pyramid (so that the extra bits at the left hand side are corrected mid-loop rather than at the end), every message on the bottom bar is now in inverse video, and re-added the all-important 3D effect on the pyramid which all this UDG malarkey was for in the first place! [IL22]
(Also, did anyone notice the UDG in the Illuminati logo? There is one...)

Can we add a sixth UDG so that the hatching line in the logo joins up?
It'll mean rehashing the code again... and recalculating the checksum... but this wasn't too much of a pain. (Such is the value of doing all the assembly on a spreadsheet so that values are automatically recalculated!)
Implemented this, corrected a few more cosmetic issues, and made a few more optimisations to same a bit of memory. [IL23]
660 bytes left after a successful game.

Is it worth trying to rework the logo... it would require moving the UDGs to a lower block, and dropping the top of BASIC a bit further... *and* reassembling all the rest of the code...
...or, better still, just copy the character set, redefine as many characters (and their inverses) as necessary, and save the whole character set (at 5120-7167), then read it back in from the main program.

AND IT ABSOLUTELY *WILL NOT* SAVE PROPERLY!

There's one way I can see to do it, maybe...
...try the save program on a C64, if it can be forced to put the code in the right place?
(But maybe the space 5120-7167 is already occupied...)


6 May 2022:
================================================================================
Ran a quick C64 program to check what's in memory locations 5120-7167. It appears to be clear (just blocks of 0s and 255s).
No idea where the BASIC is located, but still...
The code poking program doesn't work on C64 (and the character set will have to be transferred from elsewhere anyway!)

Adapted ILREAD to read back the character set, exactly as it was saved, regardless of errors, read it back and start the character set... and this confirms, there are definitely errors in the SAVED version, so it is a write error. WHY?
Asked again on the Lemon64 forums (and hope they're not ignoring me now) with a mock-up program (udgtest7) to poke an upside-down version of the VIC's character set to 5120-7167, save it as .SEQ and read it back again, checking against what's in memory. So anyone can see what's going wrong now!

IL23 works as it is (with the old logo) - but to make a new version where all the code is poked in from BASIC, we can't have DATA statements all over the place, some of which are missed because the VIC-20 doesn't have a line pointer attached to RESTORE - it's either move to the start of the list or don't move at all. Hence there has to be a workaround to get define the array C%. [IL24]
(This gives a CODE ERROR - checksum=22894, though it seems to work OK. And all the hex codes are printed in the right place.)

Meanwhile... made a version of IL24 with a new Illuminati logo that looks like the ZX81 versions, but which pokes all the MC from BASIC. And that means it needs to be reassembled for a 16K expansion, because the 8K model won't accommodate all those extra numbers in the listing. This allows two extra lines below the logo on the main screen but the instructions still can't be compacted into fewer pages. Curse that small screen! [IL25]
6,809 bytes left after a successful game. 10,295 bytes used.

Successfully managed (in an outside program) to get the machine code into three REM statements. Transplanted this into the main listing. [IL26]
8,472 bytes left after a successful game. 7,912 bytes used.
Maybe it can be cut down further by using the same technique with the UDGs as with the array C%, i.e. using a string (recycle J$, may as well) to implant the correct values. If it's slower it'll only have to be done once per load. [IL27]
8,489 bytes left after a successful game. 7,895 bytes used.
Maybe compress it more by also changing the fully-defined graphics to this technique. [IL28]
8,469 bytes left now... bah! 7,915 bytes used. Bah again!

Tried IL26 on an 8K expanded machine. It doesn't run out of memory! Only 280 bytes left, though. Tried IL28 as well, 277 bytes left.
Changing the array J% to J in IL28; 276 bytes left. It *costs* a byte! (Or, rather, using J% saves a byte...)
Optimise IL26 instead (adding a % onto CC,TH,BH costs memory).
Managed to cut it - using multi-statement lines and re-using dummy variables - so that now 450 bytes are free at the end of a successful game. 7,742 bytes used. [IL29]
(Can also delete line 10 which is now inaccurate! That'll save a few bytes. Getting rid of all the REMs bar 1-4 would save more space, but if the ZX81 version could be full of them, so can this!)


7 May 2022:
================================================================================
Gah. There's a problem with the score fuse when it runs down to 1 try left. Fixed this, added a couple of captions and made another brief optimisation to make the FINAL DEFINITIVE VIC-20 VERSION of the game! [IL30]
447 bytes remain of the 8K model after a successful game - 7,745 bytes used and it runs fine.

Just need to get it onto a separate disc (and tape) and of course there's a problem with saving it. SAVE"ILLUMINATI",8,1 apparently does not cause the VIC-20 to remember that it was loaded at 8192 instead of the default.


8 May 2022:
================================================================================
https://www.lemon64.com/forum/viewtopic.php?p=966676#966676
Hope sprange eternal with this auto-loader program... and the spring ran dry as it caused a CPU jam.


9 May 2022:
================================================================================
It isn't the loader program that's causing the CPU jam, it looks to be executing the machine code to LDIR the ROM character set in place while the disc is still spinning. Added the line:
9015 FORN=1TO5000:NEXTN
...to pause a bit before poking the graphics. But this didn't help.

Moved the BASIC down to 7168 to give it a bit more space. Hence POKE 44,28:POKE 7168,0:NEW
...and some reassembled code. This was not a problem. [IL31]
1,471 bytes available after a successful game. 7,745 bytes used out of 9,216 available.
Tried this with the loader program and it jammed at $1CCB (7371)... which is within the program. WTF?


13 May 2022: v1.0
================================================================================
Not getting anywhere with external loader programs - but with a quick look through the VIC-20 manual, threw in a few sound effects that vaguely resemble the Spectrum version (at least there's rising, falling and crash sounds as well as the Direct Line jingle). [IL32]
933 bytes left after a successful game. Hence 8,283 bytes used.

Still room for a few more optimisations and (hopefully!) getting rid of the variable X$ in favour of using SPC (which I'd forgotten - d'oh! TAB, I found, causes problems which SPC doesn't - sometimes TAB forgets to TAB...?). This might also clear up the problems on the PET. [IL33]
1,001 bytes left after a successful game. Hence 8,215 bytes used.

itsP came up with the goods with a program that will automatically shift BASIC to the correct place and auto-load the main game! However it still requires a RUN. I can LOAD"*",8,1 and press SHIFT+RUN/STOP (SHIFT+ESC on the PC keyboard) to make it auto-run (a bit like LRUN versus LOAD on the QL), but the C64 auto-run program might still work if it can be translated.
https://stackoverflow.com/questions/4344234/how-to-autostart-a-program-from-floppy-disk-on-a-commodore-c64
POKE 770 and 771 will be a two-byte value - low byte / high byte address of the Main BASIC Program Loop. See: https://www.c64-wiki.com/wiki/Page_3
According to the VIC memory map, this address is the same. The value poked into the C64 is 42115 - and the POKEs to the same address to load it in the save routine total is 43121.


22 May 2022: v1.1
================================================================================
Some tweaks to the released version, after some developments on the PET version...
Added "crash" sound effect to all three of the "brainlet" lines. Moved S=16 and added Q=RND(-TI) to just before the initial GOTO2000, and now a new game will GOTO that line instead of RUN. 962 bytes free after a successful game - 8,254 bytes used.




To load IL33: 165.836 sec
Bytes used: 8,215 hence: 65,720 bits = 396.295 bits/sec (probably 400 baud)
https://wav-prg.sourceforge.io/audiotap.html


